﻿using System;
using System.Data;
using System.Text;
using System.Reflection;
using System.Security.Policy;
using System.IO;
using System.Collections.Generic;
using net.veekee.common.data;

namespace net.veekee.common.rules
{
    public class RuleSetFactory<C, T> where T : AnEntry
    {
        private static int loadedRules = 0;
        public static int LoadedRules
        {
            get
            {
                return loadedRules;
            }
        }

        private static int discardedRules = 0;
        public static int DiscardedRules
        {
            get
            {
                return discardedRules;
            }
        }

        private static int erroneousRules = 0;
        public static int ErroneousRules
        {
            get
            {
                return erroneousRules;
            }
        }

        public static void LoadFromFile(String filename, List<RuleSet<C, T>> rules, List<RuleSet<C, T>> erroneousrules)
        {
            try
            {
                List<List<RuleSetLine>> entries = RuleSetFactory<C, T>.LoadEntries(filename);
                Log.GetInstance().Debug("{0} entrie(s) were found", entries.Count);

                foreach (List<RuleSetLine> entry in entries)
                {
                    RuleSet<C, T> rule = new RuleSet<C, T>();
                    rule.RuleFileName = filename;
                    try
                    {
                        rule.Load(entry);
                        if (rule.IsValid)
                        {
                            Log.GetInstance().Debug("- rule {0} is valid", rule.Name);
                            rules.Add(rule);
                            loadedRules++;
                        }
                        else
                        {
                            switch(rule.Status)
                            {
                                case DynamicClassStatus.Rejected:
                                    Log.GetInstance().Debug("- rule {0} is rejected", rule.Name);
                                    discardedRules++;
                                    break;
                                case DynamicClassStatus.Empty:
                                    Log.GetInstance().Debug("- rule {0} is empty", rule.Name);
                                    discardedRules++;
                                    break;
                                case DynamicClassStatus.Invalid:
                                    Log.GetInstance().Debug("- rule {0} is erroneous", rule.Name);
                                    erroneousrules.Add(rule);
                                    erroneousRules++;
                                    break;
                                default:
                                    Log.GetInstance().Debug("- rule {0} is unknown", rule.Name);
                                    erroneousrules.Add(rule);
                                    erroneousRules++;
                                    break;
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Log.GetInstance().Error(e.ToString());
                        erroneousrules.Add(rule);
                        erroneousRules++;
                    }
                }
            }
            catch (Exception e)
            {
                Log.GetInstance().Error(e.ToString());
            }
        }

        private static List<List<RuleSetLine>> LoadEntries(String filename)
        {
            Log.GetInstance().Debug("Loading {0} as a ruleset container", filename);
            List<RuleSetLine> commonEntries = new List<RuleSetLine>();
            List<RuleSetLine> currentRule = new List<RuleSetLine>();
            List<List<RuleSetLine>> rulesEntries = new List<List<RuleSetLine>>();
            int lineCount = 0;
            try
            {
                bool inRule = false;
                using (System.IO.StreamReader sr = new StreamReader(filename, Encoding.Default))
                {
                    while (!sr.EndOfStream)
                    {
                        lineCount++;
                        String line = sr.ReadLine();
                        String tline = line.Trim().ToLower();
                        if (tline.Length == 0)
                            continue;

                        if (!inRule && tline.StartsWith("rule "))
                        {
                            inRule = true;
                            currentRule = new List<RuleSetLine>();
                            currentRule.AddRange(commonEntries);
                        }

                        if (inRule)
                        {
                            currentRule.Add(new RuleSetLine() { Line = lineCount, Content = line });
                        }
                        else
                        {
                            commonEntries.Add(new RuleSetLine() { Line = lineCount, Content = line });
                        }

                        if (inRule && (tline.Equals("end") || tline.Equals("rule-end") || tline.Equals("end-rule")))
                        {
                            rulesEntries.Add(currentRule);
                            currentRule = null;
                            inRule = false;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Log.GetInstance().Error(e.ToString());
            }
            finally
            {
            }
            return rulesEntries;
        }
    }
}
